﻿using System;
using System.Linq;
using VSTalk.Engine.Core.Context;
using VSTalk.Engine.Core.EntitySession;
using VSTalk.Engine.Core.Event.Events;
using VSTalk.Model;
using VSTalk.Tools;

namespace VSTalk.Engine.Core.ClientManager
{
    public class ClientManager : IClientManager
    {
        private static IEventAggregator EventBus
        {
            get { return AppServices.Get<IEventAggregator>(); }
        }

        private Account Account
        {
            get { return AppServices.Get<IModelContext>().Account; }
        }

        public void AddClient(IClientInfo clientInfo)
        {
            var client = InitClient(clientInfo);
            Account.XmppClients.Add(client);
            EventBus.Publish(new ClientAddedEvent
            {
                ClientId = client.Id
            });
        }

        public void EditClient(Guid? id, IClientInfo clientInfo)
        {
            var client = (id == null) ? GetClientByClientInfo(clientInfo) : ModelContext.GetClientById((Guid)id);
            var context = SessionModel.GetClientContext(client);
            if (context.State == ClientState.Disconnected)
            {
                client.Login = clientInfo.Login;
                client.Server = clientInfo.Server;
            }
            client.Password = clientInfo.Password;
        }

        private static ISessionModel SessionModel
        {
            get { return AppServices.Get<ISessionModel>(); }
        }

        private static IModelContext ModelContext
        {
            get { return AppServices.Get<IModelContext>(); }
        }

        private static Client InitClient(IClientInfo clientInfo)
        {
            var client = new Client();
            client.Id = Guid.NewGuid();
            client.Login = clientInfo.Login;
            client.Server = clientInfo.Server;
            client.Password = clientInfo.Password;
            return client;
        }

        public void RemoveClient(Client client)
        {
            EventBus.Publish(new ClientRemovingEvent
            {
                ClientId = client.Id
            });
            Account.XmppClients.Remove(client);
        }

        private Client GetClientByClientInfo(IClientInfo clientInfo)
        {
            return Account.XmppClients.FirstOrDefault(t => t.Login == clientInfo.Login
                                                                    && t.Server == clientInfo.Server);
        }

        public void RemoveClient(IClientInfo clientInfo)
        {
            Client client = GetClientByClientInfo(clientInfo);
            if (client != null)
            {
                EventBus.Publish(new ClientRemovingEvent
                {
                    ClientId = client.Id
                });
                Account.XmppClients.Remove(client);
            }
        }
    }
}